package chen.web.blog;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.springframework.util.Assert;

import chen.web.IdEntity;

public class Category extends IdEntity{

	private String name;
	private String description;
	private  Position position;		//定位
	private List<Category> children = new LinkedList<Category>();	//子栏目
	private Blog belong;
	private Date created;
	
	protected Category(int id) {
		super(id);
		// TODO Auto-generated constructor stub
	}
	
	public Category(Blog belong, Position position){
		super(0);
		Assert.notNull(belong);
		Assert.notNull(position);
		this.belong = belong;
		if(!verifyBelong(position)){
			throw new PositionException("栏目不在所属博客下");
		}
		this.position = position;
	}

	void setId(int id){
		super.id = id;
	}

	void setBelong(Blog belong){
		this.belong = belong;
	}
	
	public void setName(String name) {
		this.name = name;
	}

	public void setDescription(String description) {
		this.description = description;
	}
	
	public String getName() {
		return name;
	}
	public String getDescription() {
		return description;
	}
	@JsonIgnore 
	public List<Category> getChildren() {
		return children;
	}
	void setChildren(List<Category> children) {
		this.children = children;
	}
	
	void addChild(Category child){
		this.children.add(child);
	}
	
	/**
	 * 给定栏目范围和id, 找出符合条件的栏目
	 * @param cat	查找范围
	 * @param id
	 * @return
	 */
	static Category getFromCategory(Category cat, int id){
		if(cat.getId() == id){
			return cat;
		}else {
			List<Category> children = cat.getChildren();
			for(Category child : children){
				Category c =  getFromCategory(child, id);
				if(c != null){
					return c;
				}
			}	
		}
		return null;
	}

	public Blog getBelong() {
		return belong;
	}

	@JsonIgnore 
	public Position getPosition() {
		return position;
	}

	void setPosition(Position position) {
		this.position = position;
	}
	
	private boolean verifyBelong(Position position){
		Category parent = position.getParent();
		Category front = position.getFront();
		if((front != null && !front.getBelong().equals(belong)) ||
				(parent != null && !parent.getBelong().equals(belong))){
			return false;
		}
		return true;
	}
	
	public boolean verifyMove(Position position){
		return verifyBelong(position) && _verifyMove(this, position.getParent());
	}
	
	private boolean _verifyMove(Category category, Category newParent){
		if(newParent == null)	return true;
		if(category.equals(newParent)){
			return false;
		}
		List<Category> children = category.getChildren();
		for(Category cat : children){
			if(!_verifyMove(cat, newParent))
				return false;
		}
		return true;
	}
	
	
	/**
	 * 栏目定位
	 * @author admin
	 *
	 */
	public static class Position{
		private Category parent;	//上级栏目
		private Category front ;	//前面的栏目
		
		public Position(Category parent, Category front){
			if((parent != null && parent.getId()==0) || (front!=null && front.getId()==0)){
				throw new IllegalArgumentException("不能使用没有持久化的栏目定位");
			}
			if(front != null && !same(front.getPosition().getParent(), parent)){
				throw new PositionException("前面的栏目必须在上级栏目下");
			}
			this.parent = parent;
			this.front  = front;
		}
		
		Position(){}
		private boolean same(Category cat1, Category cat2){
			if(cat1!=null && cat1.equals(cat2)){
				return true;
			} 
			if(cat1==null && cat1==cat2){
				return true;
			}
			return false;
		}
		
		public Category getParent() {
			return parent;
		}
		void setParent(Category parent){
			this.parent = parent;
		}

		void setFront(Category front){
			this.front = front;
		}
		
		public Category getFront() {
			return front;
		}

	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Category other = (Category) obj;
		if (id != other.id)
			return false;
		if(id == 0 || other.id == 0){
			return false;
		}
		return true;
	}
	
	@Override
	public String toString() {
		return "Category [id=" + id + ", name=" + name +  "]";
	}

	public Date getCreated() {
		return created;
	}

	void setCreated(Date created) {
		this.created = created;
	}
	
}
